// Copyright (C) Microsoft Corporation. All rights reserved.

using System;
using System.IO;
using System.Runtime.Serialization;

namespace Microsoft.VSPowerToys.VSCmdShell
{
	/// <summary>
	/// An implementation of WrappingCollection to store autocomplete entries 
    /// for the current context.
	/// </summary>
    [Serializable]
	public class AutoCompleteCollection : WrappingCollection<FileSystemInfo> 
	{
		
        /// <summary>
        /// This flag determines types of entries to autocomplete. Some command may limit
        /// auto complete entries to directories only for example.
        /// </summary>
        [Flags]
        public enum AutoCompleteTypes { Directories = 1, Files = 2, Both = Directories | Files };

        /// <summary>
        /// Possible entries will be filtered by this variable. If set to directory or files, only the relevant
        /// entries will be shown
        /// </summary>
        private AutoCompleteTypes filterBy = AutoCompleteTypes.Both;
		
        /// <summary>
        /// Base directory to look for entries
        /// </summary>
        private string lookupDirectory;

        /// <summary>
        /// Current prefix used to filter entries
        /// </summary>
        private string currentPrefix;
		
        /// <summary>
        /// Creates the auto complete list for the given parameters
        /// </summary>
        /// <param name="directory">Directory to look in to for possible entries</param>
        /// <param name="match">Match string to use</param>
        /// <param name="matchWhat">What kind of entries should be included</param>
		public void SetupList(string directory, string match, AutoCompleteTypes matchWhat)
		{
			/// Check if list has to be updated, if we have the same arguments there is
            /// no need to update the list.
			if (!(directory.Equals(this.lookupDirectory) &&
                match.Equals(this.currentPrefix) && 
                filterBy == matchWhat))
			{
                this.Clear();
				this.lookupDirectory = directory;
				this.filterBy = matchWhat;
                this.currentPrefix = match;
				FileSystemInfo[] entries;
				DirectoryInfo di = new DirectoryInfo(this.lookupDirectory);
				if (matchWhat == AutoCompleteTypes.Both )
                    entries = di.GetFileSystemInfos(match + "*");
				else if (matchWhat == AutoCompleteTypes.Directories )
                    entries = di.GetDirectories(match + "*");
				else
                    entries = di.GetFiles(match + "*");
                foreach (FileSystemInfo entry in entries)
                {
                    this.AddLast(entry);
                }
			}

        }

        #region Constructors

        public AutoCompleteCollection(string directory, AutoCompleteTypes matchWhat)
		{
			SetupList(directory,null, matchWhat);
		}

		public AutoCompleteCollection(string dir, string match, AutoCompleteTypes matchWhat)
		{
			SetupList(dir,match, matchWhat);
        }

        /// <summary>
        /// Constructor required for implementing ISerializable
        /// </summary>
        /// <param name="info"></param>
        /// <param name="context"></param>
        protected AutoCompleteCollection(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }
        
        #endregion

        /// <summary>
        /// Gets the next auto complete entry
        /// </summary>
        /// <param name="forward">If true, direction will be forward otherwise it will be backwards</param>
        /// <returns>Next entry depending on the direction</returns>
        public string GetEntry(bool forward)
		{
			if (this.Count == 0)
				return String.Empty;
            string dir = forward ? this.Next.Name : this.Previous.Name;
            //Have to quote file system objects with spaces in the names
			if (dir.IndexOf(' ') != -1 )
				dir = "\"" + dir + "\"";  
			return dir;
		}

        [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand, SerializationFormatter = true)]
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }
	}
}
